﻿namespace KeRui.Upload
{
    using System;
    using System.Collections;
    using System.IO;
    using System.Threading;
    using System.Web;

    internal class DataStore
    {
        private ArrayList mData = null;
        private Multipart.Form mForm = null;
        private Thread mThread = null;
        private bool mThreadContinue = false;
        private ArrayList mThreadData = null;

        public byte[] Add(byte[] theBuffer)
        {
            if (this.mThread != null)
            {
                this.AddAsync(theBuffer);
            }
            else
            {
                this.AddSync(theBuffer);
            }
            if (this.mForm != null)
            {
                return this.mForm.CurrentFile;
            }
            return new byte[0];
        }

        private void AddAsync(byte[] theBuffer)
        {
            lock (this.mThreadData.SyncRoot)
            {
                this.mThreadData.Add(theBuffer);
            }
        }

        private void AddSync(byte[] theBuffer)
        {
            if (theBuffer != null)
            {
                if (this.mData != null)
                {
                    this.mData.Add(theBuffer);
                }
                if (this.mForm != null)
                {
                    this.mForm.AddData(theBuffer);
                }
            }
        }

        public void Clear()
        {
            this.Flush();
            if (this.mData != null)
            {
                this.mData.Clear();
            }
            if (this.mForm != null)
            {
                this.mForm.Clear();
            }
        }

        private void ContinuousFlush()
        {
            while (this.mThreadContinue)
            {
                Thread.Sleep(250);
                this.FlushThreadData();
            }
            this.FlushThreadData();
        }

        ~DataStore()
        {
            try
            {
                this.Flush();
            }
            catch
            {
            }
        }

        public void FinishUp(HttpApplication inApp, Settings inSet)
        {
            this.Flush();
            if (this.mForm != null)
            {
                this.mForm.ClearData();
                if (inSet.Advanced.EnableLargeUploads)
                {
                    inApp.Context.Items.Add(Multipart.Form.KeyName, this.mForm);
                }
            }
        }

        private static byte[] Flatten(ArrayList inList)
        {
            int index = 0;
            int num2 = 0;
            int num3 = 0;
            int count = inList.Count;
            for (num2 = 0; num2 < count; num2++)
            {
                num3 += ((byte[]) inList[num2]).Length;
            }
            byte[] array = new byte[num3];
            for (num2 = 0; num2 < count; num2++)
            {
                byte[] buffer2 = (byte[]) inList[num2];
                buffer2.CopyTo(array, index);
                index += buffer2.Length;
                inList[num2] = null;
            }
            return array;
        }

        private void Flush()
        {
            if (this.mThread != null)
            {
                this.mThreadContinue = false;
                if (!this.mThread.Join(0x2710))
                {
                    Log.UniqueError("ABCUpload thread failed to stop after ten seconds.");
                    this.mThread.Abort();
                }
                this.mThread = null;
            }
        }

        private void FlushThreadData()
        {
            try
            {
                byte[] buffer;
                object obj2;
                bool flag;
                goto Label_0070;
            Label_0004:
                Monitor.Enter(obj2 = this.mThreadData.SyncRoot);
                try
                {
                    if (this.mThreadData.Count <= 0)
                    {
                        return;
                    }
                    buffer = (byte[]) this.mThreadData[0];
                    this.mThreadData.RemoveAt(0);
                }
                finally
                {
                    Monitor.Exit(obj2);
                }
                if (buffer != null)
                {
                    this.AddSync(buffer);
                }
            Label_0070:
                flag = true;
                goto Label_0004;
            }
            catch (Exception exception)
            {
                if (Settings.Current.Advanced.LogExceptions)
                {
                    Log.ExceptionDetails(exception);
                }
            }
        }

        public string GetBoundary()
        {
            this.Flush();
            string contentType = "";
            if ((this.mData != null) && (this.mData.Count > 0))
            {
                contentType = Multipart.Boundary.GetContentType(new MemoryStream((byte[]) this.mData[0]));
            }
            if (this.mForm != null)
            {
                contentType = this.mForm.ContentType;
            }
            return contentType;
        }

        public byte[] GetUploadData(int inBytesTotalHint)
        {
            this.Flush();
            if (this.mData != null)
            {
                return Flatten(this.mData);
            }
            if (this.mForm != null)
            {
                return this.mForm.GetData(inBytesTotalHint);
            }
            return null;
        }

        public void Init(Settings inSet, int inCodePage)
        {
            if (inSet.Advanced.EnableLargeUploads || inSet.Advanced.FixCorruptUploads)
            {
                this.mForm = new Multipart.Form(inCodePage, inSet.Advanced.EnableLargeUploads, false, inSet.Advanced.Optimization);
                if (inSet.Advanced.MultiThreaded)
                {
                    this.mThreadContinue = true;
                    this.mThreadData = new ArrayList();
                    this.mThread = new Thread(new ThreadStart(this.ContinuousFlush));
                    this.mThread.Start();
                }
            }
            else
            {
                this.mData = new ArrayList();
            }
        }
    }
}

